package com.fxu.docx2md;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fxu.docx2md.dto.MdPara;
import com.fxu.docx2md.dto.MdText;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.officeDocument.x2006.math.CTOMath;
import org.openxmlformats.schemas.officeDocument.x2006.math.CTOMathPara;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
import org.w3c.dom.Document;
import org.w3c.dom.*;

import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class DocxMain {
    public static final String book = "补表";
    public static final int minSize = 12;
    private static final Map<String, String> relMap = new ConcurrentHashMap<>();
    private static final Map<String, String> styleMap = new ConcurrentHashMap<>();

    public static String getDistPath() {
        return "/Users/fangxu/temp/upload/dev";
    }
    public static String doNotEndWP(String temp) {
        StringBuilder blder = new StringBuilder();
        List<String> arr = StrUtil.split(temp, "<w:p>");
        for (String tmp : arr) {
            if (tmp.contains("</w:p>")) {
                // 获取表格的colspan和merge
                blder.append("<w:p>").append(tmp);
            } else if (StrUtil.isBlank(tmp)) {
                blder.append("<w:p></w:p>").append(tmp);
            } else if (StrUtil.trim(tmp).startsWith("</")) {
                blder.append("<w:p></w:p>").append(tmp);
            } else {
                blder.append(tmp);
            }
        }
        return blder.toString();
    }
    public static void main(String[] args) {
        String file = "/Users/fangxu/demo/books/"+book+".docx";
        String outputDir = "/Users/fangxu/demo/books/"+book+"/";
        extractFiles(file, outputDir);
        // 图片
        File relFile = new File(outputDir + "rels.xml");
        if (relFile.isFile()) {
            Document document = XmlUtil.readXML(relFile);
            NodeList nodeList = document.getElementsByTagName("Relationship");
            for (int i = 0; i < nodeList.getLength(); i++) {
                NamedNodeMap nodeMap = nodeList.item(i).getAttributes();
                relMap.put(nodeMap.getNamedItem("Id").getNodeValue(), nodeMap.getNamedItem("Target").getNodeValue());
            }
            System.out.println(relMap);
        }
        // 字体
        relFile = new File(outputDir + "styles.xml");
        if (relFile.isFile()) {
            Document document = XmlUtil.readXML(relFile);
            NodeList nodeList = document.getElementsByTagName("w:style");
            for (int i = 0; i < nodeList.getLength(); i++) {
                NamedNodeMap nodeMap = nodeList.item(i).getAttributes();
                NamedNodeMap childMap = nodeList.item(i).getChildNodes().item(0).getAttributes();
                styleMap.put(nodeMap.getNamedItem("w:styleId").getNodeValue(), childMap.getNamedItem("w:val").getNodeValue());
            }
            System.out.println(styleMap);
        }
        List<MdPara> paraList = getParagraphs(file, outputDir);
        setLevel(paraList);
        StringBuilder builder = new StringBuilder();
        for (MdPara para : paraList) {
            // System.out.println(para.getText());
            builder.append(para.getText()).append("\n");
        }
        FileUtil.writeUtf8String(builder.toString(), outputDir + "全文/index.md");

//        String xml = "<xml-fragment>\n" +
//                "  <w:tr>\n" +
//                "    <w:tc>\n" +
//                "      <w:p>\n" +
//                "      <w:p>\n" +
//                "        <w:r>\n" +
//                "          <w:t>临床辅助检查</w:t>\n" +
//                "        </w:r>\n" +
//                "      </w:p>\n" +
//                "    </w:tc>\n" +
//                "    <w:tc>\n" +
//                "      <w:p>\n" +
//                "    </w:tc>\n" +
//                "    <w:tc>\n" +
//                "      <w:p>\n" +
//                "    </w:tc>\n" +
//                "  </w:tr>\n" +
//                "</xml-fragment>";
//        System.out.println(doNotEndWP(xml));
    }

    private static void setLevel(List<MdPara> paraList) {
        for (MdPara para : paraList) {
            para.setSize(getMaxSize(para.getTexts()));
            if (para.getSize() < minSize) para.setSize(minSize);
        }
        List<Integer> sizes = paraList.stream().map(MdPara::getSize).collect(Collectors.toSet()).stream()
                .sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        System.out.println("sizes=" + sizes);
        for (MdPara para : paraList) {
            // 标题自定义 优先
            if (para.getHeading() != null && para.getHeading() > 0) {
                para.setLevel(para.getHeading());
            } else {
                int index = sizes.indexOf(para.getSize());
                if (index < sizes.size() - 1) {
                    para.setLevel(index + 1);
                }
            }
            // System.out.println(para);
        }

        /*List<Integer> styles = paraList.stream().map(MdPara::getStyle).filter(Objects::nonNull).collect(Collectors.toSet()).stream()
                .sorted(Integer::compareTo).collect(Collectors.toList());
        System.out.println("styles=" + styles);
        for (MdPara para : paraList.stream().filter(v -> v.getStyle() != null).collect(Collectors.toSet())) {
            int index = styles.indexOf(para.getStyle());
            if (index < styles.size() - 1 && index < 5) {
                para.setLevel(index + 1);
            }
        }*/

        for (MdPara para : paraList) {
            if (para.getText().startsWith("任务背景：") || para.getText().startsWith("任务要求：")
                    || para.getText().startsWith("任务分析：") || para.getText().startsWith("任务操作：")) {
                para.setLevel(4);
            }
        }


    }

    private static int getMaxSize(List<MdText> textList) {
        return textList.stream().map(MdText::getSize).max(Integer::compareTo).orElse(minSize);
    }

    public static void extractFiles(String docxPath, String outputDir) {
        try (InputStream fis = new FileInputStream(docxPath); ZipInputStream zis = new ZipInputStream(fis)) {
            ZipEntry zipEntry = zis.getNextEntry();
            while (zipEntry != null) {
                String filePath = outputDir + File.separator + zipEntry.getName().replace("word/media", "images");
                if (!zipEntry.isDirectory() && zipEntry.getName().startsWith("word/media")) {
                    extractFile(zis, filePath);
                }
                if (zipEntry.getName().endsWith("document.xml.rels")) {
                    FileUtil.writeFromStream(zis, new File(outputDir + File.separator + "rels.xml"), false);
                }
                if (zipEntry.getName().equals("word/styles.xml")) {
                    FileUtil.writeFromStream(zis, new File(outputDir + File.separator + "styles.xml"), false);
                }
                zipEntry = zis.getNextEntry();
            }
            zis.closeEntry();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void extractFile(ZipInputStream zis, String filePath) throws IOException {
        FileUtil.writeFromStream(zis, new File(filePath), false);
    }

    public static String filterPinyin(String xml) {
        String temp = xml;
        int fromIndex = 0, toIndex; String tmp = "";
        Pattern pattern = Pattern.compile("<w:instrText[^>]*?>(.*?)<\\/w:instrText>");
        Matcher matcher = pattern.matcher(xml);
        while (matcher.find()) {
            String text = matcher.group(1);
            if (text.startsWith("EQ ")) {
                fromIndex = matcher.start();
                tmp = text;
                System.out.println(fromIndex + ": " + text);
            } else {
                tmp += text;
            }
            if (text.endsWith(")")) {
                toIndex = matcher.end();
                String replacement = "<w:t><![CDATA[" + getPinyin(tmp) + "]]></w:t>";
                String find = xml.substring(fromIndex, toIndex);
                temp = temp.replace(find, replacement);
            }
        }
        return temp;
    }

    static String pyTpl = "<b><b>{}</b><b>{}</b></b>";
    public static String getPinyin(String temp) {
        StringBuilder text = new StringBuilder();
        if (temp.startsWith("EQ") && temp.endsWith(")")) {
            int index = temp.lastIndexOf("(");
            if (index > 2) {
                temp = temp.substring(index + 1, temp.length() - 1);
                List<String> array = StrUtil.split(temp, "),");
                if (array.size() == 2) {
                    text.append(StrUtil.format(pyTpl, array.get(0), array.get(1)));
                }
            }
        }
        return text.toString();
    }

    public static List<MdPara> getParagraphs(String file, String outputDir) {
        List<MdPara> paraList = new ArrayList<>();
        try (FileInputStream fis = new FileInputStream(file); XWPFDocument document = new XWPFDocument(fis)) {
            for (IBodyElement element : document.getBodyElements()) {
                MdPara para = new MdPara();
                // 一般段落
                if (element instanceof XWPFParagraph) {
                    XWPFParagraph paragraph = (XWPFParagraph) element;
                    para.setCenter(paragraph.getAlignment() == ParagraphAlignment.CENTER);
                    if (StrUtil.isNotEmpty(paragraph.getStyleID()) && styleMap.containsKey(paragraph.getStyleID())) {
                        para.setHeading(getHeading(styleMap.get(paragraph.getStyleID())));
                    }
                    //System.out.println("paragraph=" + paragraph.getCTP());
                    List<MdText> texts = new ArrayList<>();

                    // 段公式
                    for (CTOMathPara ctoMathPara : paragraph.getCTP().getOMathParaList()) {
                        if (ctoMathPara.toString().contains("<m:jc m:val=\"center\"/>")) {
                            para.setCenter(true);
                        }
                        for (CTOMath ctoMath : ctoMathPara.getOMathList()) {
                            String xml = doMathXml(ctoMath.toString());
                            // System.out.println(xml);
                            MdText text = new MdText();
                            text.setBold(false);
                            text.setSize(minSize);
                            text.setText("\n" + xml + "\n");
                            texts.add(text);
                        }
                    }

                    // 处理行内的拼音 String tmp = "";
                    for (XWPFRun run : paragraph.getRuns()) {
                        /*if (run.getCTR().toString().contains("<w:instrText")) {
                            System.out.println(run.getCTR().getInstrTextList());
                        }*/
                        //System.out.println("run=" + run.getText(0) + "=" + run.getCTR().getInstrTextList());
                        StringBuilder text = doLinePinyin(run);
                        MdText mdText = new MdText();
                        mdText.setBold(run.isBold());
                        mdText.setSize(getFontSize(run));
                        mdText.setText(text.toString());
                        texts.add(mdText);
                    }
                    // 段落公式
                    for (CTOMath ctoMath : paragraph.getCTP().getOMathArray()) {
                        String xml = doMathXml(ctoMath.toString());
                        // System.out.println(xml);
                        MdText text = new MdText();
                        text.setBold(false);
                        text.setSize(minSize);
                        text.setText(xml + "\n"); // "\n" +
                        texts.add(text);
                    }
                    para.setTexts(texts);
                    if (CollUtil.isNotEmpty(para.getTexts())) {
                        paraList.add(para);
                    }
                    // 处理段落中的图片
                    for (XWPFRun run : paragraph.getRuns()) {
                        doParaImage(run, paraList);
                    }

                    // 方框框住内容
                    for (CTR ctr : paragraph.getCTP().getRList()) {
                        paraList.addAll(getWpsParas(ctr.xmlText()));
                    }
                }
                // 表格
                else if (element instanceof XWPFTable) {
                    XWPFTable xwpfTable = (XWPFTable) element;
                    //System.out.println(xwpfTable.getCTTbl());
                    String xml = xwpfTable.getCTTbl().toString();
                    xml = filterTableXml(xml);
                    //System.out.println(xml);

                    // 表格中的表格
                    Integer index = 0;
                    Map<Integer, String> inners = new HashMap<>();
                    String regex = "(?s)(<w:tbl[^>]*?>.*?<\\/w:tbl>)";
                    Matcher matcher = Pattern.compile(regex).matcher(xml);
                    while (matcher.find()) {
                        String tableText = matcher.group(1);
                        xml = xml.replace(tableText, "<w:p><w:tbl id=\""+(++index)+"\"/></w:p>");
                        String json = tableToJson(outputDir, tableText);
                        inners.put(index, json);
                    }

                    // 处理表格
                    String tableJson = tableToJson(outputDir, xml);
                    for (Integer integer : inners.keySet()) {
                        tableJson = tableJson.replace("{\"w:tbl\":{\"id\":"+integer+"}}", inners.get(integer));
                    }

                    MdText text = new MdText();
                    text.setBold(false);
                    text.setSize(minSize);
                    text.setText(tableJson);
                    para.setTexts(CollUtil.toList(text));
                    if (CollUtil.isNotEmpty(para.getTexts())) {
                        paraList.add(para);
                    }
                }
                // 目录或其他
                else if (element instanceof XWPFSDT) {
                    // 处理结构化文档标签（Structured Document Tag），通常用于表单等
                    // 这里只是简单打印，具体处理可能需要更复杂的逻辑
                    // 过滤目录
                    System.out.println("Structured Document Tag!=" + ((XWPFSDT) element).getElementType());
                    if (((XWPFSDT) element).getElementType() == BodyElementType.CONTENTCONTROL) {
                        System.out.println("过滤目录");
                    } else {
                        System.out.println("Structured Document Tag" + ((XWPFSDT) element).getElementType());
                        System.out.println("Structured Document Tag" + ((XWPFSDT) element).getContent().getText());
                        MdText text = new MdText();
                        text.setBold(false);
                        text.setSize(minSize);
                        text.setText(((XWPFSDT) element).getContent().getText());
                        para.setTexts(CollUtil.toList(text));
                    }
                    if (CollUtil.isNotEmpty(para.getTexts())) {
                        paraList.add(para);
                    }
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return paraList;
    }

    // 把表格转成json
    public static String tableToJson(String outputDir, String xml) {
        StringBuilder builder = new StringBuilder();
        List<String> array = StrUtil.split(xml, "<w:tc>");
        for (String temp : array) {
            if (temp.contains("</w:tc>")) {
                // 获取表格的colspan和merge
                builder.append("<w:tc").append(getTableColMerge(temp)).append(">");

                // 处理表格含有图片
                temp = doInTableImage(outputDir, temp);

                // 处理多余的<w:p>
                temp = doNotEndWP(temp);

                builder.append(temp);
            } else {
                builder.append(temp);
            }
        }
        xml = doTableBold(builder.toString());
        //System.out.println(xml);
        xml = xml.replaceAll("(?s)<w:rPr>.*?</w:rPr>", "");
        xml = xml.replaceAll("(?s)<w:pPr>.*?</w:pPr>", "");
        xml = xml.replaceAll("(?s)<w:tcPr>.*?</w:tcPr>", "");
        xml = xml.replaceAll("\\s*\\n+", "\n");

        // 处理表格中的文字空格
        xml = doTableBlank(xml, "ж");

        // 表格中含有拼音
        xml = filterPinyin(xml);

        xml = xml.replaceAll("(?s)<w:p>[\\s\\n]*</w:p>", "");
        xml = xml.replaceAll("\\s*\\n+", "\n");
        //System.out.println(xml);
        String jsonStr = "<!-- 表格 -->";
        try {
            JSONObject object = JSONUtil.parseFromXml(xml);
            jsonStr = object.toString().replace("ж", " ");
        } catch (Exception e) {
            //System.out.println(e.getMessage());
            System.out.println(xml);
        }
        return jsonStr;
    }

    public static String filterTableXml(String xml) {
        xml = xml.replaceFirst("(?s)<xml-fragment[^>]*?>", "<xml-fragment>");
        xml = xml.replaceAll("(?s) w14:paraId=\".*?\"", "");
        xml = xml.replaceAll("(?s)<w:trPr>.*?</w:trPr>", "");
        xml = xml.replaceAll("(?s)<w:tblPr>.*?</w:tblPr>", "");
        xml = xml.replaceAll("(?s)<w:gridCol>.*?</w:gridCol>", "");
        xml = xml.replaceAll("(?s)<w:tblGrid>.*?</w:tblGrid>", "");
        xml = xml.replaceAll("(?s)<w:tblPrEx>.*?</w:tblPrEx>", "");
        xml = xml.replaceAll("(?s)<w:bookmarkStart[^>]*?>", "");
        xml = xml.replaceAll("(?s)<w:bookmarkEnd[^>]*?>", "");
        xml = xml.replaceAll("<w:tr [^>]*?>", "<w:tr>");
        xml = xml.replaceAll("<w:p [^>]*?>", "<w:p>");
        xml = xml.replaceAll("<w:r [^>]*?>", "<w:r>");
        xml = xml.replaceAll("(?s)<w:r>[\\s\\n]*<w:fldChar w:fldCharType=\"begin\"/>[\\s\\n]*</w:r>", "");
        xml = xml.replaceAll("(?s)<w:r>[\\s\\n]*<w:fldChar w:fldCharType=\"end\"/>[\\s\\n]*</w:r>", "");
        xml = xml.replaceAll("\\s*\\n+", "\n");
        return xml;
    }

    // 处理段内图片
    public static void doParaImage(XWPFRun run, List<MdPara> paraList) {
        if (run.getCTR().toString().contains("<a:blip r:embed=")) {
            String regex = "(?s)<a\\:blip r\\:embed\\=\"(.*?)\">";
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(run.getCTR().toString());
            if (matcher.find()) {
                String rId = matcher.group(1);
                String target = relMap.get(rId);
                if (StrUtil.isNotEmpty(target)) {
                    System.out.println(rId + "=" + relMap.get(rId));

                    target = target.replace("media/", "");
                    paraList.add(getImagePara(target));
                }
            }
        }
        List<XWPFPicture> list = run.getEmbeddedPictures();
        if (list != null) {
            for (XWPFPicture picture : list) {
                // String id = picture.getCTPicture().getBlipFill().getBlip().getEmbed();
                String name = picture.getPictureData().getPackagePart().getPartName().getName();
                // System.out.println(picture.getCTPicture().getBlipFill().getBlip().getEmbed());
                // System.out.println(picture.getPictureData().getPackagePart().getPartName());
                name = name.replace("/word/media/", "");
                paraList.add(getImagePara(name));
            }
        }
    }

    // 处理一行内的拼音
    public static StringBuilder doLinePinyin(XWPFRun run) {
        String tmp = "";
        StringBuilder text = new StringBuilder();
        // 拼音
        List<CTText> instrTextList = run.getCTR().getInstrTextList();
        if (run.getText(0) == null && CollUtil.isNotEmpty(instrTextList)) {
            text = new StringBuilder();
            for (CTText ctText : instrTextList) {
                if (ctText.getStringValue().startsWith("EQ ")) {
                    tmp = ctText.getStringValue();
                } else {
                    tmp += ctText.getStringValue();
                }
                if (ctText.getStringValue().endsWith(")")) {
                    //System.out.println(tmp);
                    text.append(getPinyin(tmp));
                }
                //System.out.println(ctText.getStringValue() + "," + instrTextList.size());
                //text.append(getPinyin(ctText.getStringValue()));
            }
        }
        if (run.getText(0) != null) {
            text.append(run.getText(0));
        }
        return text;
    }

    // 处理公式
    public static String doMathXml(String xml) {
        xml = xml.replaceFirst("(?s)<m:f[^>]*?>", "<m:f>");
        xml = xml.replaceFirst("(?s)<m:r[^>]*?>", "<m:r>");
        xml = xml.replaceFirst("(?s)<m:sSub[^>]*?>", "<m:sSub>");
        xml = xml.replaceFirst("(?s)<m:acc[^>]*?>", "<m:acc>");
        xml = xml.replaceFirst("(?s)<xml-fragment[^>]*?>", "<xml-fragment>");
        xml = xml.replaceAll("(?s)<m:rPr>.*?</m:rPr>", "");
        xml = xml.replaceAll("(?s)<w:rPr>.*?</w:rPr>", "");
        xml = xml.replaceAll("(?s)<m:fPr>.*?</m:fPr>", "");
        xml = xml.replaceAll("(?s)<m:ctrlPr>.*?</m:ctrlPr>", "");
        xml = xml.replaceAll("\\s*\\n+", "\n");
        xml = xml.replaceAll("\\n", "");
        xml = xml.replaceAll(">\\s+<", "><");
        return xml;
    }

    // 把空格缓存蒙古语言ж，因为转json会过滤前后空格
    public static String doTableBlank(String xml, String com) {
        String regex = "(<w:t[^>]*?>)(.*?)<\\/w:t>";
        Matcher matcher = Pattern.compile(regex).matcher(xml);
        while (matcher.find()) {
            String text = matcher.group(2);
            if (!StrUtil.trim(text).equals(text)) {
                xml = xml.replace(matcher.group(1) + text + "</w:t>", matcher.group(1)
                        + text.replace(" ", com) + "</w:t>");
            }
        }
        return xml;
    }

    // 表格中文字是否加粗
    public static String doTableBold(String xml) {
        StringBuilder builder = new StringBuilder();
        List<String> array = StrUtil.split(xml, "<w:r>");
        for (String temp : array) {
            if (temp.contains("</w:r>")) {
                builder.append("<w:r");
                if (temp.contains("<w:b/>")) builder.append(" bold=\"1\"");
                builder.append(">");
                builder.append(temp);
            } else {
                builder.append(temp);
            }
        }
        return builder.toString();
    }

    // 表格中的图片
    public static String doInTableImage(String outputDir, String temp) {
        // 含有图片
        if (temp.contains("<w:drawing>")) {
            String target = "";
            int srt = temp.indexOf("<w:drawing>");
            int end = temp.indexOf("</w:drawing>") + "</w:drawing>".length();
            String tmp = temp.substring(srt, end);
            if (tmp.contains("<a:blip r:embed=\"")) {
                tmp = tmp.substring(tmp.indexOf("<a:blip r:embed=\"") + "<a:blip r:embed=\"".length());
                String rId = tmp.substring(0, tmp.indexOf("\"/>"));
                target = relMap.get(rId);
                if (StrUtil.isNotEmpty(target)) {
                    target = target.replace("media/", "");
                    // 拷贝图片到指定位置
                    FileUtil.copy(outputDir + "/images/" + target, getDistPath() + "/books/" + target, true);
                    target = "<![CDATA[<img src='http://localhost:91/jjcm/upload/dev/books/"+target+"' width='100%'>]]>";
                }
            }
            if (StrUtil.isEmpty(target)) {
                temp = temp.substring(0, srt) + temp.substring(end);
            } else {
                temp = temp.substring(0, srt) + "<w:t>" + target + "</w:t>" + temp.substring(end);
            }
        }
        return temp;
    }

    // 表格的列和合并
    public static StringBuilder getTableColMerge(String tcTemp) {
        String vMerge = null;
        Integer colSpan = null;
        StringBuilder builder = new StringBuilder();
        if (tcTemp.contains("<w:tcPr>")) {
            int srt = tcTemp.indexOf("<w:tcPr>");
            int end = tcTemp.indexOf("</w:tcPr>") + "</w:tcPr>".length();
            JSONObject wtc = JSONUtil.parseFromXml(tcTemp.substring(srt, end));
            Map<String, Object> tcPrMap = (Map<String, Object>) wtc.get("w:tcPr");
            if (tcPrMap.get("w:gridSpan") != null) {
                colSpan = (Integer) ((Map<String, Object>)tcPrMap.get("w:gridSpan")).get("w:val");
            }
            if (tcPrMap.get("w:vMerge") != null && tcPrMap.get("w:vMerge") instanceof Map) {
                vMerge = ((Map<String, Object>)tcPrMap.get("w:vMerge")).get("w:val").toString();
            }
        }
        if (colSpan != null) builder.append(" colSpan=").append(colSpan);
        if (vMerge != null) builder.append(" vMerge=\"").append(vMerge).append("\"");
        if (tcTemp.contains("<w:jc w:val=\"center\"/>")) builder.append(" align=\"center\"");
        return builder;
    }

    public static int getHeading(String style) {
        if (StrUtil.isEmpty(style)) return 0;
        if (style.startsWith("heading ") || style.startsWith("标题 ")) {
            style = style.replace("heading ", "").replace("标题 ", "");
            if (style.contains(" ")) {
                return Integer.parseInt(style.substring(0, style.indexOf(" ")));
            } else if (NumberUtil.isNumber(style)) {
                return Integer.parseInt(style);
            }
        }
        return 0;
    }

    public static MdPara getImagePara(String name) {
        MdPara para = new MdPara();
        MdText text = new MdText();
        text.setBold(false);
        text.setSize(minSize);
        text.setText("![](../images/" + name + ")");
        para.setTexts(CollUtil.toList(text));
        para.setImage(true);
        return para;
    }

    public static List<MdPara> getWpsParas(String xmlFragment) {
        // <mc:AlternateContent> <mc:Choice Requires="wps">
        List<MdPara> paraList = new ArrayList<>();
        int sta = xmlFragment.indexOf("<mc:Choice Requires=\"wps\">");
        int end = xmlFragment.indexOf("</mc:Choice>");
        if (sta > -1 && end > sta) {
            xmlFragment = xmlFragment.substring(sta, end);
            List<String> list = StrUtil.split(xmlFragment, "<w:p ");
            for (String s : list) {
                if (s.endsWith("</w:p>")) {
                    MdPara para = new MdPara();
                    para.setInfo(true);
                    para.setCenter(s.contains("<w:jc w:val=\"center\"/>"));
                    String regex = "(?s)<w\\:t>(.*?)<\\/w\\:t>"; //<w\:sz w\:val\="(.*?)"\/>.*
                    Pattern pattern = Pattern.compile(regex);
                    Matcher matcher = pattern.matcher(s);
                    if (matcher.find()) {
                        // String fontSize = matcher.group(1);
                        String wText = matcher.group(1);
                        MdText text = new MdText();
                        text.setBold(s.contains("<w:b/>"));
                        text.setSize(minSize);
                        text.setText(wText);
                        para.setTexts(CollUtil.toList(text));
                    }
                    paraList.add(para);
                }
            }
        }
        return paraList;
    }

    public static String getLeTeX(String xmlFragment) {
        String tag = "http://schemas.openxmlformats.org/officeDocument/2006/math";
        try {
            // 解析 XML 字符串
            Document document = XmlUtil.readXML(new StringReader(xmlFragment));

            // 查找数学公式部分
            NodeList nodeList = document.getElementsByTagNameNS(tag, "f");
            if (nodeList.getLength() > 0) {
                Element mathElement = (Element) nodeList.item(0);

                // 提取分子和分母
                String numerator = extractTextFromElement(mathElement.getElementsByTagNameNS(tag, "num").item(0));
                String denominator = extractTextFromElement(mathElement.getElementsByTagNameNS(tag, "den").item(0));

                // 转换为 LaTeX 语法
                String latexFormula = "\\frac{" + numerator + "}{" + denominator + "}";

                // 如果需要，可以添加前置文本
                NodeList textNodes = document.getElementsByTagNameNS(tag, "t");
                if (textNodes.getLength() > 0) {
                    String prefixText = extractTextFromElement(textNodes.item(0));
                    latexFormula = prefixText + " = " + latexFormula;
                }

                // 输出 LaTeX 公式
                return latexFormula;
            } else {
                System.out.println("No math formula found in the XML fragment.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    private static String extractTextFromElement(Node node) {
        StringBuilder text = new StringBuilder();
        NodeList childNodes = node.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node child = childNodes.item(i);
            if (child.getNodeType() == Node.TEXT_NODE) {
                text.append(child.getNodeValue());
            } else if (child.getNodeType() == Node.ELEMENT_NODE) {
                // 如果元素内部还有嵌套元素，可能需要递归处理（这里简化处理）
                text.append(child.getTextContent());
            }
        }
        return text.toString().trim();
    }

    private static int getFontSize(XWPFRun run) {
        return run.getFontSizeAsDouble() == null ? minSize : run.getFontSizeAsDouble().intValue();
    }
}